package com.qinyu.treehole.controller;

import com.qinyu.treehole.annotation.UserAuth;
import com.qinyu.treehole.bo.LoginUserBo;
import com.qinyu.treehole.bo.RegisterUserBo;
import com.qinyu.treehole.bo.UpdateUserBo;
import com.qinyu.treehole.entities.R;
import com.qinyu.treehole.entities.User;
import com.qinyu.treehole.service.FeedService;
import com.qinyu.treehole.service.UserService;
import com.qinyu.treehole.tool.FeedTool;
import com.qinyu.treehole.tool.UserTool;
import com.qinyu.treehole.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/user")
@Slf4j
@Validated
public class UserController {


    @Autowired
    private UserService userService;
    @Autowired
    private FeedService feedService;
    @Autowired
    private RedisTemplate jsonRedisTemplate;
    private final Object lock = new Object();

    @PostMapping("/login")
    public R login(@Validated LoginUserBo loginUserBo){
        log.info("用户:{}请求登录", loginUserBo);
        User user = userService.getUserByUserName(loginUserBo.getName());

        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }

        if(!userService.isPasswordValid(loginUserBo.getPassword(), user.getPassword())){
            return R.no(null, UserTool.USER_LOGIN_FAIL);
        }

        String token = userService.setTokenForLoginUser(user.getId());

        LoginUserVo loginUserVo = userService.parseUserToLoginUserVo(user, token);
        return R.ok(loginUserVo, UserTool.USER_LOGIN_SUCCESS);
    }

    @UserAuth
    @PostMapping("/autoLogin")
    public R autoLogin(@RequestParam("userId") Integer userId){
        log.info("用户id:{}自动登录成功...", userId);
        User user = userService.getById(userId);
        AutoLoginUserVo autoLoginUser = userService.parseUserToAutoLoginUser(user);
        return R.ok(autoLoginUser);
    }

    @UserAuth
    @PostMapping("/exit")
    public R exitLogin(@RequestParam("userId") Integer userId){
        log.info("用户id:{}已退出...", userId);
        userService.exitLoginUser(userId);
        return R.ok(null, UserTool.USER_EXIT_LOGIN_SUCCESS);
    }

    @PostMapping("/register")
    public R register(@Validated RegisterUserBo registerUserBo){
        log.info("用户:{}尝试注册...", registerUserBo);
        // 1. 判断用户名字、邮箱是否存在
        User userByName = userService.getUserByUserName(registerUserBo.getName());
        if(null != userByName){
            return R.no(null, UserTool.USER_NAME_EXIST);
        }

        User userByEmail = userService.getUserByUserEmail(registerUserBo.getEmail());
        if(null != userByEmail){
            return R.no(null, UserTool.USER_EMAIL_EXIST);
        }

        // 2. 都不存在，将registerUserBo注册到redis中并返回唯一激活码
        String code = userService.getActiveCodeAndSetUser(registerUserBo);

        return R.ok(code, UserTool.USER_REGISTER_SUCCESS);
    }

    @GetMapping("/active")
    public R active(@RequestParam("code") String code){
        log.info("激活码:{}尝试激活...", code);
        return userService.activeAndRegisterUser(code);
    }

    @UserAuth
    @GetMapping("/set")
    public R queryUserSet(@RequestParam("userId")Integer userId){
        log.info("用户id:{}查询自己信息...", userId);
        User user = userService.getById(userId);
        if(user == null) return R.no(null, UserTool.USER_NO_EXIST);

        UserSetVo userSetVo = userService.parseUserToUserSetVo(user);
        return R.ok(userSetVo, UserTool.USER_QUERY_SUCCESS);
    }

    @UserAuth
    @PutMapping
    public R update(@Validated UpdateUserBo updateUserBo){
        log.info("用户id:{}修改自己信息...", updateUserBo.getUserId());
        boolean f = false;

        // 防止并发大量人重复修改
        synchronized (lock){
            User user = userService.getUserByUserName(updateUserBo.getName());
            if(user != null && user.getId() != updateUserBo.getUserId()){
                return R.no(null, UserTool.USER_NAME_EXIST);
            }
            f = userService.updateUserByUpdateUserBo(updateUserBo);
        }

        if(f) return R.ok(null, UserTool.USER_UPDATE_SUCCESS);

        return R.no(null, UserTool.USER_UPDATE_FAIL);
    }

    @GetMapping("/{id}")
    public R index(@PathVariable("id")Integer id){
        User user = userService.getById(id);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        UserIndexVo vo = userService.getUserIndexVoByUser(user);
        return R.ok(vo, UserTool.USER_QUERY_SUCCESS);
    }

    @UserAuth
    @GetMapping("/u/{id}")
    public R indexLogin(@PathVariable("id")Integer id,
                        @RequestParam("userId")Integer userId){
        log.info("用户id:{}用户id:{}首页查询中...", userId, id);
        User user = userService.getById(id);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        UserIndexVo vo = null;
        if(id == userId){
            vo = userService.getUserIndexVoBySelfUserLogin(user);
        }else{
            vo = userService.getUserIndexVoByUserLogin(user, userId);
        }
        return R.ok(vo, UserTool.USER_QUERY_SUCCESS);
    }

    @GetMapping("/feed")
    public R getUserFeed(@RequestParam("userId")Integer userId){
        User user = userService.getById(userId);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        List<ForwardFeedVo> feeds = feedService.getForwardFeedVoByUserId(userId);
        return R.ok(feeds, FeedTool.FEED_QUERY_SUCCESS);
    }

    @UserAuth
    @GetMapping("/feed/u")
    public R getUserFeedLogin(@RequestParam("userId")Integer userId,
                              @RequestParam("uid")Integer uid){
        log.info("用户id:{}查询用户id:{}的空间...", userId, uid);
        User user = userService.getById(uid);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        List<LoginForwardFeedVo> feeds = null;
        if(userId == uid){
            feeds = feedService.getLoginForwardFeedVoBySelfUserId(userId);
        }else{
            feeds = feedService.getLoginForwardFeedVoByUserId(userId, uid);
        }
        return R.ok(feeds, FeedTool.FEED_QUERY_SUCCESS);
    }

    @GetMapping("/fans")
    public R getFans(@RequestParam("userId")Integer userId){
        log.info("用户id:{}的粉丝查询中...", userId);
        User user = userService.getById(userId);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        List<RelationUserVo> fans = userService.getFansRelationUserVosByUserId(userId);
        return R.ok(fans, UserTool.USER_QUERY_SUCCESS);
    }

    @UserAuth
    @GetMapping("/fans/u")
    public R getFansLogin(@RequestParam("userId")Integer userId,
                          @RequestParam("uid")Integer uid){
        log.info("用户id:{}查询用户id:{}的粉丝...", userId, uid);
        User user = userService.getById(uid);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        List<RelationLoginUserVo> fans = userService.getFansRelationLoginUserVosByUserId(userId, uid);
        return R.ok(fans, UserTool.USER_QUERY_SUCCESS);
    }

    @GetMapping("/follows")
    public R getFollows(@RequestParam("userId")Integer userId){
        log.info("用户id:{}的关注查询中...", userId);
        User user = userService.getById(userId);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        List<RelationUserVo> fans = userService.getFollowsRelationUserVosByUserId(userId);
        return R.ok(fans, UserTool.USER_QUERY_SUCCESS);
    }

    @UserAuth
    @GetMapping("/follows/u")
    public R getFollowsLogin(@RequestParam("userId")Integer userId,
                             @RequestParam("uid")Integer uid){
        log.info("用户id:{}查询用户id:{}的关注...", userId, uid);
        User user = userService.getById(uid);
        if(user == null){
            return R.no(null, UserTool.USER_NO_EXIST);
        }
        List<RelationLoginUserVo> fans = userService.getFollowsRelationLoginUserVosByUserId(userId, uid);
        return R.ok(fans, UserTool.USER_QUERY_SUCCESS);
    }

    @UserAuth
    @PostMapping("/follows")
    public R addRelation(@RequestParam("userId")Integer userId,
                         @RequestParam("followId")Integer followId){
        log.info("用户id:{}关注id:{}...", userId, followId);
        if(userId == followId){
            return R.no(null, UserTool.USER_ADD_RELATION_FAIL);
        }
        SetOperations ops = jsonRedisTemplate.opsForSet();
        ops.add(UserTool.FANS_NAME+followId, userId);
        ops.add(UserTool.FOLLOW_NAME+userId, followId);
        return R.ok(null, UserTool.USER_ADD_RELATION_SUCCESS);
    }

    @UserAuth
    @DeleteMapping("/follows")
    public R removeRelation(@RequestParam("userId")Integer userId,
                         @RequestParam("followId")Integer followId){
        log.info("用户id:{}取关id:{}...", userId, followId);
        if(userId == followId){
            return R.no(null, UserTool.USER_ADD_RELATION_FAIL);
        }
        SetOperations ops = jsonRedisTemplate.opsForSet();
        ops.remove(UserTool.FANS_NAME+followId, userId);
        ops.remove(UserTool.FOLLOW_NAME+userId, followId);
        return R.ok(null, UserTool.USER_DELETE_RELATION_SUCCESS);
    }
}
